package com.dries.portal.module.coupon.executor;

import com.dries.portal.module.coupon.enums.CouponCategory;
import com.dries.portal.module.coupon.enums.RuleFlag;
import com.dries.common.exception.ApiException;
import com.dries.portal.module.coupon.vo.SettlementInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 优惠券结算规则执行管理器
 * 根据用户请求（SettlementInfo） 找到对应得Executor，去做结算
 * BeanPostProcessor: Bean 的后置处理器
 * @Author ZSY
 * @createTime 2020/8/3 15:04
 */
@Slf4j
@Component
public class ExecuteManager implements BeanPostProcessor {

    /**
     * 规则执行器映射
     */
    private static final Map<RuleFlag, RuleExecutor> executorIndex = new LinkedHashMap<>();

    /**
     * 优惠券结算规则计算入口
     * 优惠券个数必须大于大于1
     */
    public SettlementInfo computeRule(SettlementInfo settlement) {
        SettlementInfo result = null;

        // 单类优惠券
        if (settlement.getCouponAndTemplateInfos().size() == 1) {
            // 获取优惠券的类别
            CouponCategory category = CouponCategory.of(
                    settlement.getCouponAndTemplateInfos().get(0).getTemplate().getCategory().getCode()
            );

            switch (category) {
                case MANJIAN:
                    result = executorIndex.get(RuleFlag.MANJAIN)
                            .computeRule(settlement);
                    break;
                case ZHEKOU:
                    result = executorIndex.get(RuleFlag.ZHEKOU)
                            .computeRule(settlement);
                    break;
                case LIJIAN:
                    result = executorIndex.get(RuleFlag.LIJIAN)
                            .computeRule(settlement);
                    break;
            }
        } else {
            // 多类优惠券
            List<CouponCategory> categories = new ArrayList<>();

            settlement.getCouponAndTemplateInfos().forEach(e ->
                    categories.add(CouponCategory.of(e.getTemplate().getCategory().getCode())));

            if (categories.size() != 2) {
                throw new ApiException("不支持更多的优惠券模板");
            } else if (categories.contains(CouponCategory.LIJIAN) &&
                    categories.contains(CouponCategory.ZHEKOU)) {
                result = executorIndex.get(RuleFlag.MANJIAN_ZHEKOU)
                        .computeRule(settlement);
            } else {
                throw new ApiException("不支持该类型的优惠券模板");
            }
        }

        return result;

    }

    /**
     * 在 Bean初始化之前去执行
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        if (!(bean instanceof RuleExecutor)) {
            return bean;
        }

        RuleExecutor executor = (RuleExecutor) bean;
        RuleFlag ruleFlag = executor.ruleConfig();
        if (executorIndex.containsKey(ruleFlag)) {
            throw new IllegalStateException("当前执行器已注册，ruleFlag:" + ruleFlag);
        }

        log.info("加载执行器 {}， 执行器规则 {}", executor.getClass(), ruleFlag);
        executorIndex.put(ruleFlag, executor);

        return null;
    }

    /**
     * 在 Bean初始化之后去执行
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
